package com.gugee.ins.common.dal.spider;

import com.gugee.common.exception.BizException;
import com.gugee.ins.common.constant.RedisKeyConst;
import com.gugee.ins.common.dal.spider.config.SpiderConfig;
import com.gugee.ins.common.model.spider.app.media.InsAppGetProductMediaResponse;
import com.gugee.ins.common.model.spider.app.media.InsAppMarkedMediaResponse;
import com.gugee.ins.common.model.spider.app.media.InsAppMediaResponse;
import com.gugee.ins.common.model.spider.media.EdgeMediaBody;
import com.gugee.ins.common.model.spider.media.InsMediaResponse;
import com.xiguaji.boot.retry.RetryableException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.concurrent.TimeUnit;

/**
 * InsBloggerSpiderClient
 * @author HuangXin
 */
@Slf4j
@Component
public class InsMediaSpiderClient {
    /**
     * restTemplate
     */
    @Autowired
    RestTemplate restTemplate;

    /**
     * redis
     */
    @Autowired
    SpiderConfig spiderConfig;

    /**
     * redis
     */
    @Autowired
    RedisTemplate<String,String> redisTemplate;

    private static final String BIZ_SPIDER_STATUS_ERROR ="BIZ_SPIDER_STATUS_ERROR";
    private static final String URI =". uri:";
    /**
     * 根据uid获取blogger 帖子列表
     * @param userId
     * @param count
     * @param endCursor
     * @return
     */
    @Retryable(value = RetryableException.class, maxAttemptsExpression = "${ins.spider.insMedia.retry:1}")
    public EdgeMediaBody getMediaByUid(long userId, Integer count, String endCursor) {
        String uri = spiderConfig.getHost() + "/Ins/MediaListByUserId?userId={userId}";
        if(count != null && count > 0){
            uri += "&count=" + count;
        }
        uri += "&end_cursor={endCursor}";

        spiderSleep(RedisKeyConst.SPIDER_MEDIA,spiderConfig.getSpiderMediaSleepSecond());
        ResponseEntity<InsMediaResponse> responseEntity = restTemplate.getForEntity(uri, InsMediaResponse.class, userId,endCursor);

        if (responseEntity.getStatusCode() != HttpStatus.OK) {
            throw new BizException(String.format("get ins Media error. status: %s . msg: %s",
                    responseEntity.getStatusCodeValue(), responseEntity.getBody()),BIZ_SPIDER_STATUS_ERROR);
        }
        if (responseEntity.getBody() == null || responseEntity.getBody().getData() == null
                || responseEntity.getBody().getData().getUser() == null
                || responseEntity.getBody().getData().getUser().getEdgeOwnerToTimelineMedia() == null) {
            throw new RetryableException("get ins Media error, retry times " + spiderConfig.getSpiderMediaRetryTimes() + URI +
                    uri.replace("{userId}", userId + "").replace("{endCursor}",endCursor));
        }
        return responseEntity.getBody().getData().getUser().getEdgeOwnerToTimelineMedia();
    }

    /**
     * 根据uid 从app端获取blogger 帖子列表
     * @param userId
     * @param endCursor
     * @return
     */
    @Retryable(value = RetryableException.class, maxAttemptsExpression = "${ins.spider.insAppMedia.retry:1}")
    public InsAppMediaResponse getAppMediaByUid(long userId, String endCursor) {
        String uri = spiderConfig.getHost() + "/InsApp/MediaListByUserId?userId={userId}";
        uri += "&max_id={endCursor}";

        spiderSleep(RedisKeyConst.SPIDER_MEDIA,spiderConfig.getSpiderAppMediaSleepSecond());
        ResponseEntity<InsAppMediaResponse> responseEntity = restTemplate.getForEntity(uri, InsAppMediaResponse.class, userId,endCursor);

        if (responseEntity.getStatusCode() != HttpStatus.OK) {
            throw new BizException(String.format("get ins app Media error. status: %s . msg: %s",
                    responseEntity.getStatusCodeValue(), responseEntity.getBody()),BIZ_SPIDER_STATUS_ERROR);
        }
        if (responseEntity.getBody() == null || responseEntity.getBody().getItems() == null) {
            throw new RetryableException("get ins app Media error, retry times " + spiderConfig.getSpiderAppMediaRetryTimes() + URI +
                    uri.replace("{userId}", userId + "").replace("{endCursor}",endCursor));
        }
        return responseEntity.getBody();
    }

    /**
     * 根据productId 获取提及该商品的帖子
     * @param productId
     * @param endCursor
     * @return
     */
    @Retryable(value = RetryableException.class, maxAttemptsExpression = "${ins.spider.insAppMediaGetProductMarkedList.retry:1}")
    public InsAppGetProductMediaResponse getProductMarkedMediaList(long productId, String endCursor) {
        String uri = spiderConfig.getHost() + "/InsApp/GetProductMarkedList?productId={productId}";
        uri += "&max_id={endCursor}";

        spiderSleep(RedisKeyConst.SPIDER_MEDIA,spiderConfig.getSpiderAppGetProductMarkedListSleepSecond());
        ResponseEntity<InsAppGetProductMediaResponse> responseEntity = restTemplate.getForEntity(uri, InsAppGetProductMediaResponse.class, productId,endCursor);

        if (responseEntity.getStatusCode() != HttpStatus.OK) {
            throw new BizException(String.format("Get insProductMarkedList error. status: %s . msg: %s",
                    responseEntity.getStatusCodeValue(), responseEntity.getBody()),BIZ_SPIDER_STATUS_ERROR);
        }
        if (responseEntity.getBody() == null || responseEntity.getBody().getItems() == null) {
            throw new RetryableException("get insProductMarkedList error, retry times " + spiderConfig.getSpiderAppGetProductMarkedListRetryTimes() + URI +
                    uri.replace("{productId}", productId + "").replace("{endCursor}",endCursor));
        }
        return responseEntity.getBody();
    }

    /**
     * 根据uId 获取提及该播主的帖子
     * @param uid
     * @param endCursor
     * @return
     */
    @Retryable(value = RetryableException.class, maxAttemptsExpression = "${ins.spider.insAppMediaGetMarkedMediaList.retry:1}")
    public InsAppMarkedMediaResponse getMarkedMediaByUserId(long uid, String endCursor) {
        String uri = spiderConfig.getHost() + "/InsApp/MarkedListByUserId?userId={uid}";
        uri += "&max_id={endCursor}";

        spiderSleep(RedisKeyConst.SPIDER_MEDIA,spiderConfig.getSpiderAppGetMarkedMediaByUserIdSleepSecond());
        ResponseEntity<InsAppMarkedMediaResponse> responseEntity = restTemplate.getForEntity(uri, InsAppMarkedMediaResponse.class, uid,endCursor);

        if (responseEntity.getStatusCode() != HttpStatus.OK) {
            throw new BizException(String.format("Get insMarkedMediaList by uid error. status: %s . msg: %s",
                    responseEntity.getStatusCodeValue(), responseEntity.getBody()),BIZ_SPIDER_STATUS_ERROR);
        }
        if (responseEntity.getBody() == null || responseEntity.getBody().getItems() == null) {
            throw new RetryableException("get insMarkedMediaList by uid error, retry times " + spiderConfig.getSpiderAppGetMarkedMediaListRetryTimes() + URI +
                    uri.replace("{uid}", uid + "").replace("{endCursor}",endCursor));
        }
        return responseEntity.getBody();
    }

    /**
     * 爬完就睡眠 防止风控
     */
    private void spiderSleep(String redisKey,long ms){
        if(ms > 0) {
            while (isSleep(redisKey,ms)) {
                //睡眠
                try {
                    Thread.sleep(ms);
                } catch (Exception e) {
                    log.error("spider sleep error,msg:{}",e.getMessage());
                }
            }
        }
    }

    private boolean isSleep(String redisKey,long ms){
        return !redisTemplate.opsForValue().setIfAbsent(redisKey, System.currentTimeMillis() + "", ms, TimeUnit.MILLISECONDS);
    }
}
